package tech.wetech.admin.core.utils;

import com.alibaba.fastjson.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.*;

/**
 * Description : HTTP工具类. <br />
 * Create Time : 2014年10月11日 下午2:05:40 <br />
 * Copyright : Copyright (c) 2010 - 2014 All rights reserved. <br />
 * 
 * @author Yanshaodong
 * @version 1.0
 */
public class HttpUtils {

	private static final Log log = LogFactory.getLog(HttpUtils.class);

	private static final String AMP = "&";

	private static final int SIZE = 1024 * 1024;

	private HttpUtils() {
	}

	/**
	 * 获得发送数据
	 * 
	 * @param strUrl
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public static List<String> get(String strUrl, Map<String, Object> map) throws Exception {
		String strtTotalURL = "";
		List<String> result = new ArrayList<String>();
		if (strtTotalURL.indexOf("?") == -1) {
			strtTotalURL = strUrl + "?" + getUrl(map);
		} else {
			strtTotalURL = strUrl + "&" + getUrl(map);
		}
		URL url = new URL(strtTotalURL);
		BufferedReader in = null;
		try {
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setUseCaches(false);
			HttpURLConnection.setFollowRedirects(true);
			in = new BufferedReader(new InputStreamReader(con.getInputStream()), SIZE);

			log.info("###### Content-Type: " + con.getRequestProperty("Content-Type") + ", Url: " + con.getURL());
			while (true) {
				String line = in.readLine();
				if (line == null) {
					break;
				} else {
					result.add(line);
				}
			}
		} catch (Exception e) {
			log.info("excetpin, strUrl" + strUrl + ",Map=" + map);
			e.printStackTrace();
		} finally {
			if (in != null) {
				in.close();
			}
		}
		return result;
	}

	/**
	 * 获得发送数据
	 * 
	 * @param urlStr
	 * @param content
	 * @param charset
	 * @return
	 * @throws IOException
	 */
	public static String post(String urlStr, String content, String charset) throws IOException {
		String totalURL = null;
		if (urlStr.indexOf("?") == -1) {
			totalURL = urlStr + "?" + content;
		} else {
			totalURL = urlStr + "&" + content;
		}
		URL url = new URL(totalURL);
		HttpURLConnection con = (HttpURLConnection) url.openConnection();
		con.setDoInput(true);
		con.setDoOutput(true);
		con.setAllowUserInteraction(false);
		con.setUseCaches(false);
		con.setRequestMethod("POST");
		con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);

		BufferedWriter bout = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), charset));
		bout.write(content);
		bout.flush();
		bout.close();
		log.info("###### Content-Type: " + con.getRequestProperty("Content-Type") + ", Url: " + con.getURL());
		BufferedReader bin = new BufferedReader(new InputStreamReader(con.getInputStream(), charset), SIZE);
		List<String> result = new ArrayList<String>();
		while (true) {
			String line = bin.readLine();
			if (line == null) {
				break;
			} else {
				result.add(line);
			}
		}
		return result.toString();
	}


	public static String postJson(String strUrl, Map<String,Object> map){
		try {
			CloseableHttpClient httpClient = HttpClients.createDefault();
			HttpPost post = new HttpPost(strUrl);
			post.setHeader("Content-Type","application/json;charset=utf-8");
			StringEntity postingString = new StringEntity(JSON.toJSONString(map),
					"utf-8");
			post.setEntity(postingString);
			HttpResponse response = httpClient.execute(post);
			String content = EntityUtils.toString(response.getEntity(),"UTF-8");
			return content;
		} catch (SocketTimeoutException e) {
			Map<String,Object> maps=new HashMap<>();
			maps.put("code",6);
			maps.put("msg","连接超时");
			return JSON.toJSONString(maps);
		} catch (Exception e) {
			Map<String,Object> maps=new HashMap<>();
			maps.put("code",7);
			maps.put("msg","系统异常");
			return JSON.toJSONString(maps);
		}
	}

	public static String postsJson(String strUrl, Map<String,Object> map){
		try {
			CloseableHttpClient httpClient = HttpClients.createDefault();
			RequestConfig requestConfig = RequestConfig.custom()
					.setSocketTimeout(100 * 1000)
					.setConnectTimeout(100 * 1000)
					.build();
			HttpPost post = new HttpPost(strUrl);
			post.setConfig(requestConfig);
			post.setHeader("Content-Type","application/json;charset=utf-8");
			StringEntity postingString = new StringEntity(JSON.toJSONString(map),
					"utf-8");
			post.setEntity(postingString);
			HttpResponse response = httpClient.execute(post);
			String content = EntityUtils.toString(response.getEntity(),"UTF-8");
			return content;
		} catch (SocketTimeoutException e) {
			Map<String,Object> maps=new HashMap<>();
			maps.put("code",6);
			maps.put("msg","连接超时");
			return JSON.toJSONString(maps);
		} catch (Exception e) {
			Map<String,Object> maps=new HashMap<>();
			maps.put("code",7);
			maps.put("msg","系统异常");
			return JSON.toJSONString(maps);
		}
	}

	/**
	 * 获得发送数据
	 * 
	 * @param strUrl
	 * @param map
	 * @param charset
	 * @return
	 * @throws IOException
	 */
	public static String post(String strUrl, Map<String, Object> map, String charset) throws IOException {
		String content = getUrl(map);
		String totalURL = null;
		if (strUrl.indexOf("?") == -1) {
			totalURL = strUrl + "?" + content;
		} else {
			totalURL = strUrl + "&" + content;
		}
		URL url = new URL(totalURL);
		HttpURLConnection con = (HttpURLConnection) url.openConnection();
		con.setDoInput(true);
		con.setDoOutput(true);
		con.setAllowUserInteraction(false);
		con.setUseCaches(false);
		con.setRequestMethod("POST");
		con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);

		BufferedWriter bout = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), charset));
		bout.write(content);
		bout.flush();
		bout.close();
		log.info("###### Content-Type:" + con.getRequestProperty("Content-Type") + ", Url: " + con.getURL());
		BufferedReader bin = new BufferedReader(new InputStreamReader(con.getInputStream(), charset), SIZE);
		String result = "";
		while (true) {
			String line = bin.readLine();
			if (line == null) {
				break;
			} else {
				result = line;
			}
		}
		return result.toString();
	}

	@Deprecated
	public static String postJson1(String strUrl, String json, String charset) throws Exception {
		URL url = new URL(strUrl);
		HttpURLConnection con = (HttpURLConnection) url.openConnection();
		con.setDoInput(true);
		con.setDoOutput(true);
		con.setAllowUserInteraction(false);
		con.setUseCaches(false);
		con.setRequestMethod("POST");
		con.setRequestProperty("Content-Type", "application/json;charset=" + charset);
		con.connect();
		
		BufferedWriter bout = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), charset));
		bout.write(json);
		bout.flush();
		bout.close();
		log.info("###### Content-Type:" + con.getRequestProperty("Content-Type") + ", Url: " + con.getURL());
		BufferedReader bin = new BufferedReader(new InputStreamReader(con.getInputStream(), charset), SIZE);
		List<String> result = new ArrayList<String>();
		while (true) {
			String line = bin.readLine();
			if (line == null) {
				break;
			} else {
				result.add(line);
			}
		}
		return result.toString();
	}

	/* ========================== 辅助方法 ========================== */

	/**
	 * MAP参数转化URL参数
	 * 
	 * @param map
	 * @return
	 */
	private static String getUrl(Map<String, Object> map) {
		if (null == map || map.keySet().size() == 0) {
			return "";
		}
		StringBuffer url = new StringBuffer();
		Set<String> keys = map.keySet();
		for (Iterator<String> i = keys.iterator(); i.hasNext();) {
			String key = i.next();
			if (map.containsKey(key)) {
				Object val = map.get(key);
				String str = val != null ? val.toString() : "";
				url.append(key).append("=").append(str).append(AMP);
			}
		}
		String strURL = "";
		strURL = url.toString();
		if (AMP.equals("" + strURL.charAt(strURL.length() - 1))) {
			strURL = strURL.substring(0, strURL.length() - 1);
		}
		return strURL;
	}

	/** 创建可关闭的httpClient客户端对象 */
	private CloseableHttpClient httpClient;
	/** 定义状态码 */
	private int statusCode;
	/** 定义响应内容 */
	private String content;

	/** 定义构造器 */
	public HttpUtils(boolean https){
		try{
			/** 判断是否为HTTPS协议 */
			if (https) {
				SSLConnectionSocketFactory sslsf =
						new SSLConnectionSocketFactory(SSLContext.getDefault());
				httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			} else {
				httpClient = HttpClients.createDefault();
			}
		}catch(Exception ex){
			throw new RuntimeException(ex);
		}
	}

	public String sendGet(String url, Map<String,String> params){
		try{
			/** 创建URI构建对象 */
			URIBuilder uriBuilder = new URIBuilder(url);
			/** 创建HttpGet请求方式对象 */
			HttpGet httpGet = new HttpGet(uriBuilder.build());
			return execute(httpGet,params);
		}catch(Exception ex){
			throw new RuntimeException(ex);
		}
	}

	/** 执行请求方法 */
	private String execute(HttpUriRequest httpUriRequest,Map<String,String> params)throws Exception{
		/** 执行请求，得到可关闭的响应对象 */
		CloseableHttpResponse response = null;
		try{
			httpUriRequest.addHeader("Authorization",params.get("token"));
			response = httpClient.execute(httpUriRequest);
			/** 设置响应状态码 */
			this.setStatusCode(response.getStatusLine().getStatusCode());
			if (response.getEntity() != null){
				content = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
			}
			return content;
		}finally{
			if (response != null){
				try {
					response.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public int getStatusCode() {
		return statusCode;
	}
	public void setStatusCode(int statusCode) {
		this.statusCode = statusCode;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
}